package com.jf.identity.service.impl;

import com.jf.identity.dao.vis.ExamInfoDao;
import com.jf.identity.dao.vis.FoulCodeDao;
import com.jf.identity.dao.visexamid.FoulFeedBackDao;
import com.jf.identity.entity.*;
import com.jf.identity.exception.ServiceException;
import com.jf.identity.holder.ExamBaseParamHolder;
import com.jf.identity.service.FoulCodeService;
import com.jf.identity.util.Params;
import com.jf.identity.util.PostPictureUtil;
import com.jf.identity.util.TaskUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Created by x on 2018/4/12.
 */
@Service
public class FoulCodeServiceImpl implements FoulCodeService {
    private static final String EMERGENCY_READ = "4";
    @Resource
    private ExamBaseParamHolder examBaseParamHolder;
    @Resource
    private ExamInfoDao examInfoDao;
    @Resource
    private FoulCodeDao foulCodeDao;
    @Resource
    private FoulFeedBackDao foulFeedBackDao;
    @Resource
    private ExamBaseParamValidator examBaseParamValidator;

    private Logger logger = LoggerFactory.getLogger(getClass());

    @Override
    public FoulCode getFoulCodes() {
        ExamBaseParam examBaseParam = examBaseParamHolder.getExamBaseParam();
        ExamBaseParam.isBlank(examBaseParam);
        //对考场的机构代码、考试计划编号做空值验证
        examBaseParamValidator.validate(examBaseParam,ExamBaseParam.EXAM_ID, ExamBaseParam.ORGCODE);
        //首先要从考试信息去拿到违纪库id，然后再去找到对应的信息
        ExamInfo examInfo = examInfoDao.getExamInfoByExamId(examBaseParam.getExamId());
        String foulCodeId = examInfo.getFoulCodeId();
        if (StringUtils.isEmpty(foulCodeId)) {
            throw new ServiceException("未找到对应的违纪违规库Id");
        }
        return foulCodeDao.getFoulCodesById(foulCodeId);
    }

    @Override
    public boolean setFoulInfoBatch(FoulFeedBackBatch foulFeedBackBatch) {
        List<FoulFeedBackInfo> foulFeedBackInfos = foulFeedBackBatch.getExaminees();
        Boolean isFoul = foulFeedBackBatch.getFoulStatus();
        if (isFoul == null) {
            throw new IllegalStateException("请上传：违纪/缺考标记");
        }
        foulFeedBackBatch.setDateTime(new Date());
        ExamBaseParam examBaseParam = examBaseParamHolder.getExamBaseParam();
        ExamBaseParam.isBlank(examBaseParam);
        examBaseParamValidator.validate(examBaseParam,ExamBaseParam.EXAM_ID, ExamBaseParam.ORGCODE,
                ExamBaseParam.EXAM_SESSION_NUM, ExamBaseParam.LOGIC_EXAM_ROOM_NUM);
        String examId = examBaseParam.getExamId();
        String orgCode = examBaseParam.getOrgCode();
        String examSessionNum = examBaseParam.getExamSessionNum();
        String logicExamRoom = examBaseParam.getLogicExamRoomNum();

        //设置每条违纪信息的uid,并将每张照片的路径拼接存入images里
        for (FoulFeedBackInfo foulFeedBackInfo : foulFeedBackInfos) {
            Params.isBlank(foulFeedBackInfo, "违纪/缺考信息");
            String examineeNo = foulFeedBackInfo.getExamineeNo();
            String code = foulFeedBackInfo.getCode();
            String source = foulFeedBackInfo.getSource();
            // uid = MD5(examId+orgCode+examSessionNum+logicExamRoomNum+examineeNo+code)
            String md5
                    = getFoulFeedBackInfoMd5(examId, orgCode, examSessionNum,
                    logicExamRoom, examineeNo, code,
                    source);
            foulFeedBackInfo.setUid(md5);
            List<Photo> photos = foulFeedBackInfo.getPhoto();
            String imageUrls;
            StringBuilder imageUrlsSB = new StringBuilder();
            if(photos != null && !photos.isEmpty()){
                for (Photo p : photos) {
                    if(!StringUtils.isEmpty(p.getFile())) {
                        String pic = PostPictureUtil.postPicAtLocal(p.getFile(),"8", examBaseParam.getExamId());
                        imageUrlsSB.append(pic).append(";");
                    }
                }
                if (StringUtils.isEmpty(imageUrlsSB)) {
                    imageUrls = "";
                } else {
                    imageUrls = imageUrlsSB.toString();
                }
                foulFeedBackInfo.setImageUrls(imageUrls);
            }
        }
        //为以防重复提交导致 将重复提交的图片信息进行删除操作
        List<FoulFeedBackInfo> foulFeedBackInfoListOld = foulFeedBackDao.getPhotoUrls(foulFeedBackInfos);
        for (FoulFeedBackInfo ff : foulFeedBackInfoListOld) {
            String picOldPath = ff.getImageUrls();
            if (!StringUtils.isEmpty(picOldPath)) {
                //先要解析字符串，然后执行删除操作
                String[] images = picOldPath.split(";");
                String drive = PostPictureUtil.drive;
                for (String s : images) {
                    PostPictureUtil.deleteLocalPic(drive + s);
                }
            }
        }
        int i;
        //提交违纪--insert
        if (isFoul) {
            i = foulFeedBackDao.insertFoulInfos(examBaseParam, foulFeedBackInfos);
        } else {
            //取消违纪--delete
            List<String> uids = foulFeedBackInfos.stream().map(
                    (FoulFeedBackInfo::getUid)).collect(Collectors.toList()
            );
            i = foulFeedBackDao.deleteFoulInfoByUids(uids);
        }
        TaskUtil.submit(() -> {
            examBaseParamHolder.setExamBaseParam(examBaseParam);
            setFinalFoulInfoBatch(foulFeedBackBatch);
        });
        return i != 0;
    }

    @Override
    public boolean setFinalFoulInfoBatch(FoulFeedBackBatch foulFeedBackBatch) {
        ExamBaseParam examBaseParam = examBaseParamHolder.getExamBaseParam();
        ExamInfo examInfo = examInfoDao.getExamInfoByExamId(examBaseParam.getExamId());
        //获取缺考 code:
        String foulCodeId = examInfo.getFoulCodeId();
        FoulCode foulCode = foulCodeDao.getFoulCodesById(foulCodeId);
        List<FoulCodeDetail> foulCodeDetails = foulCode.getFoulCodeDetails();
        //type为0表示缺考的违纪信息
        String absentCode = null;
        for (FoulCodeDetail f : foulCodeDetails) {
            if ("0".equals(f.getType())) {
                absentCode = f.getCode();
                break;
            }
        }

        Boolean isFoul = foulFeedBackBatch.getFoulStatus();

        //上报缺考信息
        List<FoulFeedBackInfo> absentInfos = new ArrayList<>();
        //上报违纪信息
        List<FoulFeedBackInfo> foulInfos = new ArrayList<>();
        for (FoulFeedBackInfo foulFeedBackInfo : foulFeedBackBatch.getExaminees()) {
            //{考试计划编号}_{准考证号}_{场次}
            String uid = examBaseParam.getExamId() + "_"
                    + foulFeedBackInfo.getExamineeNo() + "_" + examBaseParam.getExamSessionNum();
            foulFeedBackInfo.setUid(uid);
            foulFeedBackInfo.setDateTime(foulFeedBackBatch.getDateTime());
            if (foulFeedBackInfo.getCode().equals(absentCode)) {
                absentInfos.add(foulFeedBackInfo);
            } else {
                foulInfos.add(foulFeedBackInfo);
            }
        }
        //上报缺考：
        foulFeedBackBatch.setExaminees(absentInfos);
        int i = 0;
        int j = 0;
        if (!absentInfos.isEmpty()) {
            i = foulFeedBackDao.updateFinalAbsentInfo(examBaseParam, foulFeedBackBatch);
            logger.debug("\r\n上报缺考至 v_examinee_final_vodinfo_{},共{} 条", examBaseParam.getExamSessionNum(), i);
        }
        if (!foulInfos.isEmpty()) {
            if (isFoul) {
                //上报违纪：
                foulFeedBackDao.delFinalFoulInfo(examBaseParam, foulInfos);
                j = foulFeedBackDao.insertFinalFoulInfo(examBaseParam, foulInfos);
            } else {
                //取消违纪:
                j = foulFeedBackDao.delFinalFoulInfo(examBaseParam, foulInfos);
            }
            logger.debug("\r\n上报违纪至 v_examinee_final_vodinfo_{},共{} 条", examBaseParam.getExamSessionNum(), j);
        }
        return i != 0 || j != 0;
    }

    /**
     * 根据 违纪信息 按MD5方式生成 UID
     *
     * @param examId         考试计划编号
     * @param orgCode        机构代码
     * @param examSessionNum 考试场次
     * @param logicExamRoom  逻辑考场号
     * @param examineeNo     考试号
     * @param code           违纪代码
     * @param source         上报来源
     * @return MD5生成的UID
     */
    private String getFoulFeedBackInfoMd5(String examId, String orgCode, String examSessionNum,
                                          String logicExamRoom, String examineeNo, String code,
                                          String source) {
        String uid = examId + orgCode + examSessionNum + logicExamRoom + examineeNo + code + source;
        return DigestUtils.md5DigestAsHex(uid.getBytes(Charset.forName("UTF-8")));
    }
    //:下面的方法主要解决的问题是对于缺考与违纪二者冲突的处理，现由于产品的需求故没有用下面的实现
    //如果后期会有此处理可按照以下的代码实现
//    @Override
//    public boolean insertFoulInfo(FoulFeedBackInfo foulFeedBackInfo) {
//        ExamBaseParam examBaseParam = examBaseParamHolder.getExamBaseParam();
//        //对考场的机构代码、机构识别码、考试计划编号、考试场次编号、逻辑考场号做空值验证
//        if(StringUtils.isEmpty(examBaseParam.getExamId())||
//                StringUtils.isEmpty(examBaseParam.getExamSessionNum())||
//                StringUtils.isEmpty(examBaseParam.getLogicExamRoomNum())||
//                StringUtils.isEmpty(examBaseParam.getOrgCode())||
//                StringUtils.isEmpty(examBaseParam.getorgIdenCode())){
//            throw new ServiceException("考场基本信息输入有误");
//        }
//        //todo:根据foulStatus来判断是插入违纪信息还是取消违纪信息
//        int n = 0;
//        if(foulFeedBackInfo.getFoulStatus()){
//            /*
//             * 此处包含违纪与缺考的处理
//             * 首先通过违纪库id获取详细的违纪代码
//             * 然后找到缺考的违纪代码
//             * 通过缺考的违纪代码去判断上传的是违纪还是缺考，用于插入数据中
//             */
//            ExamInfo examInfo = examInfoDao.getExamInfoByExamId(examBaseParam.getExamId());
//            String foulCodeId = examInfo.getFoulCodeId();
//            if(StringUtils.isEmpty(foulCodeId)){
//                throw new ServiceException("未找到对应的违纪违规库Id");
//            }
//            FoulCode foulCode = foulCodeDao.getFoulCodesById(foulCodeId);
//            List<FoulCodeDetail> foulCodeDetails = foulCode.getFoulCodeDetails();
//            //type为0表示缺考的违纪信息
//            FoulCodeDetail foulCodeDetail = null;
//            for ( FoulCodeDetail f:foulCodeDetails) {
//                if("0".equals(f.getType())){
//                    foulCodeDetail = f;
//                }
//            }
//            if(foulCodeDetail==null){
//                throw new ServiceException("未找到缺考的违纪信息");
//            }
//            //这里构造一个用于判断是缺考还是违纪的入参foulfeedbackinfo
//            FoulFeedBackInfo foulFeedBackInfoJudge = new FoulFeedBackInfo();
//            foulFeedBackInfoJudge.setExamineeNo(foulFeedBackInfo.getExamineeNo());
//            //必须传入的是缺考的code
//            foulFeedBackInfoJudge.setCode(foulCodeDetail.getCode());
//            //如果是缺考
//            if(foulCodeDetail.getCode().equals(foulFeedBackInfo.getCode())){
//                //如果是缺考就看数据库是否有违纪信息
//                int a = foulFeedBackDao.hasViolateInfo(examBaseParam,foulFeedBackInfoJudge);
//                //如果有违纪信息，说明上传的缺考信息是错乱的
//                if(a!=0){
//                    return false;
//                }
//                //插入需要uuid
//                foulFeedBackInfo.setUid(UUIDUtil.generateUUID());
//                int i = foulFeedBackDao.deleteFoulInfo(examBaseParam,foulFeedBackInfo);
//                n = foulFeedBackDao.insertFoulInfo(examBaseParam,foulFeedBackInfo);
//            }else {
//                //如果是违纪就看数据库是否有缺考信息
//                int a = foulFeedBackDao.hasAbsentInfo(examBaseParam,foulFeedBackInfoJudge);
//                //如果有缺考信息，说明上传的违纪信息是错乱的
//                if(a!=0){
//                    return false;
//                }
//                //插入需要uuid
//                foulFeedBackInfo.setUid(UUIDUtil.generateUUID());
//                int i = foulFeedBackDao.deleteFoulInfo(examBaseParam,foulFeedBackInfo);
//                n = foulFeedBackDao.insertFoulInfo(examBaseParam,foulFeedBackInfo);
//            }
//        }else {
//            n = foulFeedBackDao.deleteFoulInfo(examBaseParam,foulFeedBackInfo);
//        }
//        return n!=0;
//    }
}
